﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data;
using System.Linq.Expressions;
using MyVoteMVC.Common.Specifications;
using MyVoteMVC.Data;

namespace MyVoteMVC.Data.Repositories
{
    public class AdminRepository<TEntity> : IAdminRepository<TEntity> where TEntity : class
    {
        public VoteDBContext ctx { set; get; }

        #region IRepository<TEntity> Members

        public virtual IQueryable<TEntity> QueryableEntity()
        {
            return ctx.Set<TEntity>();
        }

        public virtual IEnumerable<TEntity> GetAll()
        {
            return ctx.Set<TEntity>();
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="Id">表的主键</param>
        /// <returns></returns>
        public virtual TEntity GetEntityById(string Id)
        {
            TEntity entity = ctx.Set<TEntity>().Find(Id);
            return entity;
        }

        public TEntity GetEntityById(params object[] values)
        {
            TEntity entity = ctx.Set<TEntity>().Find(values);
            return entity;
        }


        public virtual bool Add(TEntity entity)
        {
            try
            {
                ctx.Entry(entity).State = EntityState.Added;
            }
            catch
            {
                return false;
            }
            return true;
        }

        public virtual bool Update(TEntity entity)
        {
            try
            {
                ctx.Entry(entity).State = EntityState.Modified;
            }
            catch
            {
                return false;
            }
            return true;
        }

        public virtual bool Delete(string id)
        {
            try
            {
                TEntity entity = ctx.Set<TEntity>().Find(id);
                Delete(entity);
            }
            catch
            {
                return false;
            }

            return true;
        }

        public virtual bool Delete(TEntity entity)
        {
            if (ctx.Entry<TEntity>(entity).State == EntityState.Detached)
            {
                ctx.Set<TEntity>().Attach(entity);
            }

            ctx.Set<TEntity>().Remove(entity);
            return true;
        }

        public virtual bool Delete(IEnumerable<TEntity> entitys)
        {
            try
            {
                foreach (TEntity entity in entitys)
                    Delete(entity);
            }
            catch
            {
                return false;
            }

            return true;
        }

        public virtual IEnumerable<TEntity> GetMany(ISpecification<TEntity> specification)
        {
            return ctx.Set<TEntity>().Where(specification.IsSatisfiedBy());
        }

        public virtual IEnumerable<TEntity> GetMany(Expression<Func<TEntity, bool>> expression)
        {
            return ctx.Set<TEntity>().Where(expression);
        }


        public IEnumerable<TEntity> GetAll<TKey>(Expression<Func<TEntity, TKey>> orderby)
        {
            return ctx.Set<TEntity>().OrderBy(orderby);
        }

        public IEnumerable<TEntity> GetAll<TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderby, out int count)
        {
            if (pageIndex < 0)
            {
                throw new ArgumentNullException("pageIndex必须大于或等于0");
            }

            if (pageSize < 0)
            {
                throw new ArgumentNullException("pageSize必须大于或等于0");
            }

            int skipCount = pageIndex * pageSize;
            count = ctx.Set<TEntity>().Count();
            return ctx.Set<TEntity>().OrderBy(orderby).Skip(skipCount).Take(pageSize);
        }


        public IEnumerable<TEntity> GetMany<TKey>(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, TKey>> orderby)
        {
            return ctx.Set<TEntity>().Where(expression).OrderBy(orderby);
        }

        public IEnumerable<TEntity> GetMany<TKey>(Expression<Func<TEntity, bool>> expression, int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderby, out int count)
        {
            if (pageIndex < 0)
            {
                throw new ArgumentNullException("pageIndex必须大于或等于0");
            }

            if (pageSize < 0)
            {
                throw new ArgumentNullException("pageSize必须大于或等于0");
            }

            int skipCount = pageIndex * pageSize;
            count = ctx.Set<TEntity>().Where(expression).Count();
            return ctx.Set<TEntity>().Where(expression).OrderBy(orderby).Skip(skipCount).Take(pageSize);
        }

        public IEnumerable<TEntity> GetMany<TKey>(ISpecification<TEntity> specification, Expression<Func<TEntity, TKey>> orderby)
        {
            return ctx.Set<TEntity>().Where(specification.IsSatisfiedBy()).OrderBy(orderby);
        }

        public IEnumerable<TEntity> GetMany<TKey>(ISpecification<TEntity> specification, int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderby, out int count)
        {
            if (pageIndex < 0)
            {
                throw new ArgumentNullException("pageIndex必须大于或等于0");
            }

            if (pageSize < 0)
            {
                throw new ArgumentNullException("pageSize必须大于或等于0");
            }

            int skipCount = (pageIndex - 1) * pageSize;
            count = ctx.Set<TEntity>().Where(specification.IsSatisfiedBy()).Count();
            return ctx.Set<TEntity>().Where(specification.IsSatisfiedBy()).OrderBy(orderby).Skip(skipCount).Take(pageSize);
        }

        #endregion

        public int GetAllCount()
        {
            return ctx.Set<TEntity>().Count();
        }

        public int GetManyCount(Expression<Func<TEntity, bool>> expression)
        {
            return ctx.Set<TEntity>().Where(expression).Count();
        }

        public int GetManyCount(ISpecification<TEntity> specification)
        {
            return ctx.Set<TEntity>().Where(specification.IsSatisfiedBy()).Count();
        }
    }
}
